package com.cole.miniapp.project.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaTemplateData;
import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage;
import com.cole.miniapp.common.utils.ServletUtils;
import com.cole.miniapp.project.domain.*;
import com.cole.miniapp.project.enumeration.pay.PayMethodEmun;
import com.cole.miniapp.project.enumeration.store.StoreOrderStateEmun;
import com.cole.miniapp.project.enumeration.store.StoreOrderTypeEmun;
import com.cole.miniapp.project.enumeration.template.MessageTemplateEmun;
import com.cole.miniapp.project.enumeration.template.NoticeTemplateEmun;
import com.cole.miniapp.project.enumeration.user.UserFractionEmun;
import com.cole.miniapp.project.enumeration.user.UserRechargeStateEmun;
import com.cole.miniapp.project.enumeration.user.UserRechargeTypeEmun;
import com.cole.miniapp.project.mapper.*;
import com.cole.miniapp.project.service.PayService;
import com.cole.miniapp.project.utils.ReplaceData;
import com.cole.miniapp.project.utils.TemplateData;
import com.cole.miniapp.project.vo.Parameter3;
import com.cole.qrcode.QrcodeUtils;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import me.chanjar.weixin.common.error.WxErrorException;

import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @Author: Ceanie
 * @Despriction:
 * @Date: Created in 16:07 2019-05-17
 * @Modify By:
 **/
@Service
public class PayServiceImpl implements PayService {


    @Autowired
    private WxPayService wxPayService;

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private WxPayNotifyMapper wxPayNotifyMapper;

    @Autowired
    private FcmUserRechargesMapper fcmUserRechargeMapper;

    @Autowired
    private FcmUserMapper fcmUserMapper;

    @Autowired
    private FcmStoreMapper fcmStoreMapper;

    @Autowired
    private FcmUserFractionMapper fcmUserFractionMapper;

    @Autowired
    private FcmUserConsumptionMapper fcmUserConsumptionMapper;

    @Autowired
    private FcmFractionProportionMapper fcmFractionProportionMapper;

    @Autowired
    private FcmStoreOperationMapper fcmStoreOperationMapper;

    @Autowired
    private FcmStoreFansMapper fcmStoreFansMapper;

    @Value("${show.row}")
    private int showRow;

    @Value("${qrcode.filepath}")
    private String qrcodeFilepath;

    @Value("${qrcode.urlpath}")
    private String qrcodeUrlPath;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public FcmUserRecharges createRecharge(FcmUser fcmUser, BigDecimal money) {
        //创建订单
        String orderNumber = UUID.randomUUID().toString().replace("-", "");
        FcmUserRecharges fcmUserRecharges = new FcmUserRecharges();
        fcmUserRecharges.setOrderNumber(orderNumber);
        fcmUserRecharges.setUserId(fcmUser.getId());
        fcmUserRecharges.setStoreId((long) 0);
        fcmUserRecharges.setStoreUserId((long) 0);
        fcmUserRecharges.setMoney(money);
        fcmUserRecharges.setState(UserRechargeStateEmun.CODE_0.getCode());
        fcmUserRecharges.setType(UserRechargeTypeEmun.CODE_0.getCode());
        fcmUserRecharges.setCreateTime(new Date());
        fcmUserRechargeMapper.insert(fcmUserRecharges);

        return fcmUserRechargeMapper.selectByPrimaryKey(orderNumber);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public WxPayMpOrderResult payRecharge(FcmUser fcmUser, String orderNumber) throws WxPayException {

        FcmUserRecharges fcmUserRecharges = fcmUserRechargeMapper.selectByPrimaryKey(orderNumber);

        //调用微信接口
        WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
        request.setAttach(UserRechargeTypeEmun.CODE_0.getMsg());
        request.setBody(UserRechargeTypeEmun.CODE_0.getMsg());
        request.setDetail(UserRechargeTypeEmun.CODE_0.getMsg());
        request.setOpenid(fcmUser.getmOpenid());
        request.setNonceStr(UUID.randomUUID().toString().replace("-", ""));
        request.setOutTradeNo(fcmUserRecharges.getOrderNumber());
        request.setSpbillCreateIp(ServletUtils.getIpAddr());
        request.setTotalFee(fcmUserRecharges.getMoney().intValue());
        BigDecimal money = fcmUserRecharges.getMoney().multiply(BigDecimal.valueOf(100));
        request.setTotalFee(money.intValue());

        WxPayMpOrderResult reponse = wxPayService.createOrder(request);

        fcmUserRecharges.setState(UserRechargeStateEmun.CODE_1.getCode());
        fcmUserRecharges.setAppid(reponse.getAppId());
        fcmUserRecharges.setPrepayId(reponse.getPackageValue());
        fcmUserRecharges.setTimeStamp(reponse.getTimeStamp());
        fcmUserRecharges.setPayTime(new Date());

        fcmUserRechargeMapper.updatePayInfoByOrderNumber(fcmUserRecharges);

        return reponse;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateOrder(WxPayOrderNotifyResult notifyResult) throws WxErrorException {
        //将返回的数据插入数据表
        WxPayNotify wxPayNotify = new WxPayNotify();
        wxPayNotify.setAppid(notifyResult.getOpenid());
        wxPayNotify.setBankType(notifyResult.getBankType());
        wxPayNotify.setFeeType(notifyResult.getFeeType());
        wxPayNotify.setIsSubscribe(notifyResult.getIsSubscribe());
        wxPayNotify.setMchId(notifyResult.getMchId());
        wxPayNotify.setOpenid(notifyResult.getOpenid());
        wxPayNotify.setOutTradeNo(notifyResult.getOutTradeNo());
        wxPayNotify.setResultCode(notifyResult.getResultCode());
        wxPayNotify.setReturnCode(notifyResult.getReturnCode());
        wxPayNotify.setTimeEnd(notifyResult.getTimeEnd());
        wxPayNotify.setTotalFee(notifyResult.getTotalFee());
        wxPayNotify.setTradeType(notifyResult.getTradeType());
        wxPayNotify.setTransactionId(notifyResult.getTransactionId());
        wxPayNotify.setCreateTime(new Date());
        wxPayNotifyMapper.insert(wxPayNotify);

        FcmUserRecharges fcmUserRecharges = fcmUserRechargeMapper.selectByPrimaryKey(notifyResult.getOutTradeNo());
        Date date = new Date();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //HH表示24小时制；
        BigDecimal money = new BigDecimal(Double.valueOf(notifyResult.getTotalFee()) / 100).setScale(2, BigDecimal.ROUND_DOWN);
        ReplaceData replaceData = new ReplaceData();

        if (fcmUserRecharges.getOrderNumber().equals(notifyResult.getOutTradeNo())) {

            //消费记录设置成充值成功
            fcmUserRecharges.setState(UserRechargeStateEmun.CODE_2.getCode());
            fcmUserRecharges.setRechargeTime(date);
            fcmUserRechargeMapper.updateStateByOrderNumber(fcmUserRecharges);

            //增加用户余额
            FcmUser fcmUser = new FcmUser();
            fcmUser.setmOpenid(notifyResult.getOpenid());
            fcmUser.setMoney(money);
            fcmUserMapper.updateMoneyByopenid(fcmUser);

            //通过openid获取用户信息
            fcmUser = fcmUserMapper.selectUserByOpenid(notifyResult.getOpenid());

            //设置发送充值成功模版消息
            List<String> list = new ArrayList<>(NoticeTemplateEmun.CODE_0.getNumber());
            list.add(fcmUserRecharges.getOrderNumber());
            list.add(fcmUser.getNickname());
            list.add(fcmUserRecharges.getMoney().toString());
            list.add(PayMethodEmun.CODE_0.getMsg());
            list.add(dateFormat.format(date));
            list.add(MessageTemplateEmun.CODE_0.getMsg());

            TemplateData templateData = new TemplateData();
            List<WxMaTemplateData> wxMaTemplateDataList = templateData
                    .setTemplateDataList(list, NoticeTemplateEmun.CODE_0.getNumber());

            WxMaTemplateMessage wxMaTemplateMessage = new WxMaTemplateMessage();
            wxMaTemplateMessage.setFormId(replaceData.replatePrepayId(fcmUserRecharges.getPrepayId()));
            wxMaTemplateMessage.setToUser(notifyResult.getOpenid());
            wxMaTemplateMessage.setTemplateId(NoticeTemplateEmun.CODE_0.getTemplateid());
            wxMaTemplateMessage.setData(wxMaTemplateDataList);

            //发送模版消息
            wxMaService.getMsgService().sendTemplateMsg(wxMaTemplateMessage);
        } else {
            //消费记录设置成充值失败
            fcmUserRecharges.setState(UserRechargeStateEmun.CODE_3.getCode());
            fcmUserRecharges.setRechargeTime(date);
            fcmUserRechargeMapper.updateStateByOrderNumber(fcmUserRecharges);

            //通过openid获取用户信息
            FcmUser fcmUser = fcmUserMapper.selectUserByOpenid(notifyResult.getOpenid());

            //设置发送的充值失败模版消息
            List<String> list = new ArrayList<>(NoticeTemplateEmun.CODE_1.getNumber());
            list.add(fcmUserRecharges.getOrderNumber());
            list.add(fcmUser.getNickname());
            list.add(fcmUserRecharges.getMoney().toString());
            list.add(dateFormat.format(date));
            list.add(MessageTemplateEmun.CODE_1.getMsg());
            list.add(MessageTemplateEmun.CODE_99.getMsg());

            TemplateData templateData = new TemplateData();
            List<WxMaTemplateData> wxMaTemplateDataList = templateData.
                    setTemplateDataList(list, NoticeTemplateEmun.CODE_1.getNumber());

            WxMaTemplateMessage wxMaTemplateMessage = new WxMaTemplateMessage();
            wxMaTemplateMessage.setFormId(replaceData.replatePrepayId(fcmUserRecharges.getPrepayId()));
            wxMaTemplateMessage.setToUser(notifyResult.getOpenid());
            wxMaTemplateMessage.setTemplateId(NoticeTemplateEmun.CODE_1.getTemplateid());
            wxMaTemplateMessage.setData(wxMaTemplateDataList);

            //发送模版消息
            wxMaService.getMsgService().sendTemplateMsg(wxMaTemplateMessage);


        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String createPaymentCode(FcmBusiness fcmBusiness, BigDecimal money,String fromId) {
        //创建消费订单
        String orderNumber = UUID.randomUUID().toString().replace("-", "");
        FcmUserConsumption fcmUserConsumption = new FcmUserConsumption();
        fcmUserConsumption.setOrderNumber(orderNumber);
        fcmUserConsumption.setStoreId(fcmBusiness.getStoreId());
        fcmUserConsumption.setStoreUserId(fcmBusiness.getUserId());
        fcmUserConsumption.setPrice(money);
        fcmUserConsumption.setState(StoreOrderStateEmun.CODE_0.getCode());
        fcmUserConsumption.setType(StoreOrderTypeEmun.CODE_1.getCode());
        fcmUserConsumption.setFormId(fromId);
        fcmUserConsumption.setCreateTime(new Date());
        fcmUserConsumptionMapper.insert(fcmUserConsumption);

        //插入门店店员操作日志
        FcmStoreOperation fcmStoreOperation = new FcmStoreOperation();
        fcmStoreOperation.setStoreId(fcmBusiness.getStoreId());
        fcmStoreOperation.setUserId(fcmBusiness.getUserId());
        fcmStoreOperation.setOperationId((long) 1);
        fcmStoreOperation.setDescription("生成收款码");
        fcmStoreOperation.setCreateTime(new Date());
        fcmStoreOperationMapper.insert(fcmStoreOperation);
        byte[] bytes = null;
        String fileName =String.format("%s.%s",orderNumber,"jpg");
        try {
            bytes = QrcodeUtils.createQrcode(orderNumber, null);

            File file = new File(String.format("%s%s",qrcodeFilepath,fileName));

            FileUtils.writeByteArrayToFile(file, bytes);
            
        } catch (IOException e) {
            e.printStackTrace();
        }

        return String.format("%s%s",qrcodeUrlPath,fileName);
    }

    @Override
    public FcmUserConsumption userScanQrcoderGetOrderInfo(String orderNumber) {
        FcmUserConsumption fcmUserConsumption = fcmUserConsumptionMapper.selectByPrimaryKey(orderNumber);
        if (fcmUserConsumption.getState() != 0 || fcmUserConsumption.getUserId() != null) {
            return null;
        }
        return fcmUserConsumption;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean userScanQrcoderPay(FcmUser fcmUser, String orderNumber) throws Exception {
        FcmUserConsumption fcmUserConsumption = fcmUserConsumptionMapper.selectByPrimaryKey(orderNumber);
        if (fcmUserConsumption.getState() != 0 || fcmUserConsumption.getUserId() != null) {
            throw new Exception("订单异常");
        }
        //判断用户余额是否充足
        BigDecimal userMoney = fcmUser.getMoney();
        BigDecimal orderMoney = fcmUserConsumption.getPrice();
        int i = userMoney.compareTo(orderMoney);
        if (i != -1) {
            Date date = new Date();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
            //更新消费订单状态
            fcmUserConsumption.setUserId(fcmUser.getId());
            fcmUserConsumption.setState(StoreOrderStateEmun.CODE_1.getCode());
            fcmUserConsumption.setCompleteTime(date);
            fcmUserConsumptionMapper.updateUserIdAndStateByOrderNumber(fcmUserConsumption);

            //获取商家信息
            FcmStore fcmStore = fcmStoreMapper.selectByPrimaryKey(fcmUserConsumption.getStoreId());

            //获取商家积分比例
            FcmFractionProportion fcmFractionProportion = fcmFractionProportionMapper.selectFractionProportionByStoreIdAndZero(fcmUserConsumption.getStoreId());
            BigDecimal proportion=new BigDecimal(1);
            if(fcmFractionProportion!=null){
                 proportion = fcmFractionProportion.getFractionProportion().multiply(BigDecimal.valueOf(100)).setScale(0, BigDecimal.ROUND_DOWN);
            }
            BigDecimal fraction = orderMoney.multiply(proportion).setScale(0, BigDecimal.ROUND_DOWN);

            //相应的门店扣除积分，增加余额，门店积分允许为负数,平台会在最后结算的时候扣除相应积分的钱
            fcmStore.setTurnover(orderMoney);
            fcmStore.setGiveFraction(fraction.longValue());
            fcmStore.setSurplusFraction(fraction.longValue());
            fcmStoreMapper.updateTurnoverById(fcmStore);

            //从用户余额扣取订单金额，并且给用户增加相应的积分
            fcmUser.setMoney(orderMoney);
            fcmUser.setFraction(fraction.longValue());
            fcmUserMapper.updateRedMoneyById(fcmUser);

             //如果增加积分不为0写入用户积分明细
            if (fraction.intValue()!=0){
                FcmUserFraction fcmUserFraction = new FcmUserFraction();
                fcmUserFraction.setOrderNumber(orderNumber);
                fcmUserFraction.setUserId(fcmUser.getId());
                fcmUserFraction.setStoreId(fcmStore.getId());
                fcmUserFraction.setFraction(fraction.longValue());
                fcmUserFraction.setState(UserFractionEmun.CODE_0.getCode());
                fcmUserFraction.setCreateTime(date);
                fcmUserFractionMapper.insert(fcmUserFraction);
            }

            if (fcmStoreFansMapper.selectByUserId(fcmUser.getId())==0){
                FcmStoreFans fcmStoreFans=new FcmStoreFans();
                fcmStoreFans.setUserId(fcmUser.getId());
                fcmStoreFans.setStoreId(fcmStore.getId());
                fcmStoreFans.setCreateTime(date);
                fcmStoreFansMapper.insert(fcmStoreFans);
            }

            //设置发送支付成功模版消息
            FcmUser toUser = fcmUserMapper.selectByPrimaryKey(fcmUserConsumption.getStoreUserId());

            List<String> list = new ArrayList<>(NoticeTemplateEmun.CODE_2.getNumber());
            list.add(orderNumber);
            list.add(fcmUser.getNickname());
            list.add(orderMoney.toString());
            list.add(dateFormat.format(date));
            list.add(MessageTemplateEmun.CODE_98.getMsg());

            TemplateData templateData = new TemplateData();
            List<WxMaTemplateData> wxMaTemplateDataList = templateData
                    .setTemplateDataList(list, NoticeTemplateEmun.CODE_2.getNumber());

            WxMaTemplateMessage wxMaTemplateMessage = new WxMaTemplateMessage();
            wxMaTemplateMessage.setFormId(fcmUserConsumption.getFormId());
            wxMaTemplateMessage.setToUser(toUser.getmOpenid());
            wxMaTemplateMessage.setTemplateId(NoticeTemplateEmun.CODE_2.getTemplateid());
            wxMaTemplateMessage.setData(wxMaTemplateDataList);

            //发送模版消息
            wxMaService.getMsgService().sendTemplateMsg(wxMaTemplateMessage);
            return true;
        }

        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int storeRechargesToUser(FcmBusiness fcmBusiness, Long userId, String phone, BigDecimal money) {
        //获取用户信息，并判断，以防充值出现错误
        FcmUser fcmUser = fcmUserMapper.selectByPrimaryKey(userId);
        if (fcmUser == null) {
            return 0;
        }
        if (!fcmUser.getPhone().equals(phone)) {
            return 1;
        }
        FcmStore fcmStore = fcmStoreMapper.selectByPrimaryKey(fcmBusiness.getStoreId());
        //比较充值金额与商店剩余金额
        BigDecimal storeMoney = fcmStore.getTurnover();
        int i = storeMoney.compareTo(money);
        if (i == -1) {
            return 2;
        }
        //商店扣除相应的金额，用户余额相应增加
        fcmStore.setTurnover(money);
        fcmStoreMapper.updateRedTurnoverById(fcmStore);
        fcmUser.setMoney(money);
        fcmUserMapper.updateAddMoneyById(fcmUser);

        //插入用户充值表记录
        FcmUserRecharges fcmUserRecharges = new FcmUserRecharges();
        fcmUserRecharges.setOrderNumber(UUID.randomUUID().toString().replace("-",""));
        fcmUserRecharges.setUserId(userId);
        fcmUserRecharges.setStoreId(fcmBusiness.getStoreId());
        fcmUserRecharges.setStoreUserId(fcmBusiness.getUserId());
        fcmUserRecharges.setMoney(money);
        fcmUserRecharges.setState(UserRechargeStateEmun.CODE_2.getCode());
        fcmUserRecharges.setType(UserRechargeTypeEmun.CODE_1.getCode());
        fcmUserRecharges.setCreateTime(new Date());
        fcmUserRechargeMapper.insert(fcmUserRecharges);

        //插入店员操作表记录
        FcmStoreOperation fcmStoreOperation = new FcmStoreOperation();
        fcmStoreOperation.setStoreId(fcmBusiness.getStoreId());
        fcmStoreOperation.setUserId(fcmBusiness.getUserId());
        fcmStoreOperation.setOperationId((long) 2);
        fcmStoreOperation.setDescription("用户充值");
        fcmStoreOperation.setCreateTime(new Date());
        fcmStoreOperationMapper.insert(fcmStoreOperation);

        return 3;
    }

    @Override
    public List<FcmUserRecharges> getRechargesList(Long id,int page) {
        Parameter3 parameter3=new Parameter3();
        parameter3.setVar1(id);
        parameter3.setVar2(page*showRow);
        parameter3.setVar3(showRow);
        return fcmUserRechargeMapper.selectRechargesByUserId(parameter3);
    }
}
